#include "cw32_hal_malloc.h"
#include <string.h>

typedef struct
{
    void		*mem_ptr;  
	uint16_t	mem_size;
	uint16_t	mem_type; 
	uint8_t		mem_index;  
}mem_block;



#if FLASH_MEMORY_ENABLE == 0

	#define _MEMORY	((MEMORY_SIZE + (NUM * sizeof(mem_block))))

#else

	#define FLASH_DEFAULT_SIZE 0x200	//0.5K用于flash缓存
	#define DEFAULT_MIX_MEM_SIZE (FLASH_DEFAULT_SIZE + sizeof(mem_block))	
	#define _MEMORY	(DEFAULT_MIX_MEM_SIZE + (MEMORY_SIZE + ((NUM) * sizeof(mem_block))))
		
#endif

static uint8_t sum = 0;
static char	mem[_MEMORY];

#define MEM_START	&mem[0]
#define MEM_END		&mem[_MEMORY]
#define BLK_SIZE	sizeof(mem_block)

static uint16_t surplus_mem_size = _MEMORY;

/**
 * @brief 申请内存池空间
 *
 * @param size :所需申请内存空间的大小
 *        参数可以是:
 *           1 ~ MEMORY_SIZE
 * @param type :使用类型,用于异步操作时使用
 *        	参数可以是: 0 - 不参与判断
 *           1 ~ 255
 * @return uint8_t :所申请的内存的句柄id,用于后续获取内存首地址/扩容/销毁等操作,非零代表申请成功
 */
uint8_t cw32_hal_malloc(uint16_t size,uint8_t type)
{
//	// <span style="color:red;">优化点 1：减少重复计算</span>
//    uint16_t all_size = size + sizeof(mem_block);

//    // <span style="color:red;">优化点 2：提前检查无效输入</span>
//    if (size == 0 || all_size > MEMORY_SIZE) {
//        return 0; // 无效输入或内存不足
//    }

//    // <span style="color:red;">优化点 3：减少嵌套层次，提高可读性</span>
//    if (sum == 0) {
//        // 首次分配逻辑
//        mem_block *new_blk = (mem_block *)MEM_START;
//        new_blk->mem_ptr = (char *)MEM_END - size;
//        new_blk->mem_size = size;
//        new_blk->mem_index = 1;
//        new_blk->mem_type = type;

//        sum = 1;
//        surplus_mem_size -= size;
//        return 1;
//    }

//    // 非首次分配逻辑
//    mem_block *last_blk = (mem_block *)(MEM_START + BLK_SIZE * (sum - 1));
//    int16_t free_blk = (char *)last_blk->mem_ptr - (MEM_START + BLK_SIZE * sum);

//    if (all_size > free_blk) {
//        return 0; // 空闲块不足
//    }

//    // 分配新块
//    mem_block *new_blk = (mem_block *)(MEM_START + BLK_SIZE * sum);
//    new_blk->mem_ptr = (char *)last_blk->mem_ptr - size;
//    new_blk->mem_size = size;
//    new_blk->mem_index = last_blk->mem_index + 1;
//    new_blk->mem_type = type;

//    sum++;
//    surplus_mem_size -= size;
//    return new_blk->mem_index;
//	
//	uint16_t all_size = size + sizeof(mem_block);
//    mem_block tmp_blk;

//    // <span style="color:red;">优化点 2：提前检查无效输入</span>
//    if (size == 0 || all_size > MEMORY_SIZE) {
//        return 0; // 无效输入或内存不足
//    }

//    // <span style="color:red;">优化点 3：减少嵌套层次，提高可读性</span>
//    if (sum == 0) {
//        // 首次分配逻辑
//        tmp_blk.mem_ptr = (char *)MEM_END - size;
//        tmp_blk.mem_size = size;
//        tmp_blk.mem_index = 1;
//        tmp_blk.mem_type = type;

//        // <span style="color:red;">优化点 4：直接写入内存，避免 memcpy</span>
//        *(mem_block *)MEM_START = tmp_blk;

//        sum = 1;
//        surplus_mem_size -= size;
//        return 1;
//    }

//    // 非首次分配逻辑
//    mem_block *ptr_blk = (mem_block *)(MEM_START + BLK_SIZE * (sum - 1));
//    int16_t free_blk = (char *)ptr_blk->mem_ptr - (MEM_START + BLK_SIZE * sum);

//    if (all_size > free_blk) {
//        return 0; // 空闲块不足
//    }

//    // 分配新块
//    tmp_blk.mem_ptr = (char *)ptr_blk->mem_ptr - size;
//    tmp_blk.mem_size = size;
//    tmp_blk.mem_index = ptr_blk->mem_index + 1;
//    tmp_blk.mem_type = type;

//    // <span style="color:red;">优化点 5：直接写入内存，避免 memcpy</span>
//    *(mem_block *)(MEM_START + BLK_SIZE * sum) = tmp_blk;

//    sum++;
//    surplus_mem_size -= size;
//    return tmp_blk.mem_index;

	uint16_t all_size = size + sizeof(mem_block);
	mem_block tmp_blk;
	
	if(size == 0) 
	{
		return 0;
	}
	
	if(sum)
	{
		mem_block *ptr_blk = (mem_block *)(MEM_START + BLK_SIZE * (sum - 1));
		int16_t free_blk = (char *)ptr_blk->mem_ptr-(MEM_START + BLK_SIZE * sum);
		if(all_size <= free_blk)
		{
			tmp_blk.mem_ptr = (char*)ptr_blk->mem_ptr - size;
			tmp_blk.mem_size = size;
			tmp_blk.mem_index = ptr_blk->mem_index + 1;
			tmp_blk.mem_type = type;
			memcpy(MEM_START + BLK_SIZE * sum, &tmp_blk, BLK_SIZE);
			sum = sum + 1;
			surplus_mem_size -= size;
			return tmp_blk.mem_index;
		}
	}

	else
	{
		if(all_size <= _MEMORY)
		{
			
			tmp_blk.mem_ptr = MEM_END - size;
			tmp_blk.mem_size = size;
			tmp_blk.mem_index = 1;
			memcpy(MEM_START, &tmp_blk, BLK_SIZE);
			sum = 1;
			surplus_mem_size -= size;
			tmp_blk.mem_type = type;
			return 1;
			
		}
	}
	return 0;
}

/**
 * @brief 申请内存池空间并赋值0其内存
 *
 * @param size :所需申请内存空间的大小
 *        参数可以是:
 *           1 ~ MEMORY_SIZE
 * @param type :使用类型,用于异步操作时使用
 *        参数可以是: 0 - 不参与判断
 *           1 ~ 255
 * @return uint8_t :所申请的内存的句柄id,用于后续获取内存首地址/扩容/销毁等操作
 */
uint8_t cw32_hal_calloc(uint16_t size,uint8_t type)
{
	uint8_t id = cw32_hal_malloc(size,type);
	
	char* p = cw32_hal_get_mem_addr(id,type);
	
	if(id != 0)
	{
		memset(p,0,size);
	}
	
	return id;
}




/**
 * @brief 重新分配当前已有的内存大小
 *
 * @param id :之前申请内存的句柄id
 * @param size :所需申请内存空间的大小
 *        参数可以是:
 *           1 ~ MEMORY_SIZE
 * @return uint8_t : 0 - 成功
					 1 - 失败
 * @note	重新分配内存后,以往的数据将会被提前,旧位置的数据不会被清洗
 */
uint8_t cw32_hal_realloc(uint8_t id, uint16_t size)
{
	for(uint8_t i=0; i<sum; i++)
	{
		mem_block *ptr_blk = (mem_block *)(MEM_START + BLK_SIZE*i);
		if(id == ptr_blk->mem_index)
		{
			int16_t free_blk = (char *)ptr_blk->mem_ptr-(MEM_START + BLK_SIZE*sum);
			int16_t old_size = ptr_blk->mem_size;
			int16_t offset = size - old_size;
			int16_t move_size = 0; 
			int16_t n = sum - i;
			mem_block *ptr_tmp;

			if(offset == 0)
			{
				return 0;
			}

			else if(offset < 0)
			{
				offset = old_size - size;
				for(uint16_t j=1; j<n; j++)
				{
					ptr_tmp = (mem_block *)(MEM_START + BLK_SIZE*(i+j));
					move_size += ptr_tmp->mem_size;
				}
				if(n == 1)
				{
					ptr_tmp = (mem_block *)(MEM_START + BLK_SIZE*i);
				}
				move_size += size;
				char *dst_addr = (char*)ptr_tmp->mem_ptr + move_size + offset - 1;
				char *src_addr = (char*)ptr_tmp->mem_ptr + move_size - 1;
				for(uint16_t j=move_size; j>0; j--)
				{
					*dst_addr-- = *src_addr--;
				}
				memset(src_addr, 0, offset+1);
				for(uint16_t j=0; j<n; j++)
				{
					ptr_tmp = (mem_block *)(MEM_START + BLK_SIZE*(i+j));
					ptr_tmp->mem_ptr =(char*)ptr_tmp->mem_ptr + offset;
					if(j == 0)
					{
						ptr_tmp->mem_size = size;
					}
				}
				return 1;
			}

			else
			{
				if(offset <= free_blk)
				{
					for(uint16_t j=1; j<n; j++)
					{
						ptr_tmp = (mem_block *)(MEM_START + BLK_SIZE*(i+j));
						move_size += ptr_tmp->mem_size;
					}
					if(n == 1)
					{
						ptr_tmp = (mem_block *)(MEM_START + BLK_SIZE*i);
					}
					move_size += old_size;
					char *dst_addr = (char*)ptr_tmp->mem_ptr - offset;
					char *src_addr = (char*)ptr_tmp->mem_ptr;
					for(uint16_t j=0; j<move_size; j++)
					{
						*dst_addr++ = *src_addr++;
					}
					for(uint16_t j=0; j<n; j++)
					{
						ptr_tmp = (mem_block *)(MEM_START + BLK_SIZE*(i+j));
						ptr_tmp->mem_ptr =(char*)ptr_tmp->mem_ptr - offset;
						if(j == 0)
						{
							ptr_tmp->mem_size = size;
						}
					}
					return 1;				
				}
			}
		}
	}
	return 0;
}



/**
 * @brief 销毁所属id的内存空间
 * @param id :之前申请内存的句柄id
 * @return uint8_t : 1 - 成功
					 0 - 失败
 */
uint8_t cw32_hal_free(uint8_t id)
{
	mem_block *ptr_blk;
	for(uint8_t i=0; i<sum; i++)
	{
		ptr_blk = (mem_block *)(MEM_START + BLK_SIZE*i);
		if(id != ptr_blk->mem_index)
		{
			continue;
		}

		mem_block *ptr_old;
		if(i != (sum-1))
		{
			int offset = ptr_blk->mem_size;
			int move_size = 0; 
			int n = sum - i;
			mem_block *ptr_tmp;
			for(int j=1; j<n; j++)
			{
				ptr_tmp = (mem_block *)(MEM_START + BLK_SIZE*(i+j));
				move_size += ptr_tmp->mem_size;
			}

			char *dst_addr = (char*)ptr_tmp->mem_ptr + move_size + offset - 1;
			char *src_addr = (char*)ptr_tmp->mem_ptr + move_size - 1;
			for(int j=move_size; j>0; j--)
			{
				*dst_addr-- = *src_addr--;
			}
			memset(src_addr, 0, offset+1);
			for(int j=0; j<(n-1); j++)
			{
				ptr_tmp = (mem_block *)(MEM_START + BLK_SIZE*(i+j));
				ptr_old = (mem_block *)(MEM_START + BLK_SIZE*(i+j+1));
				memcpy(ptr_tmp, ptr_old, BLK_SIZE);
				ptr_tmp->mem_ptr =(char*)ptr_tmp->mem_ptr + offset;
			}
		}
		else
		{
			ptr_old = (mem_block *)(MEM_START + BLK_SIZE*i);
			memset(ptr_old->mem_ptr, 0, ptr_old->mem_size);
		}
		surplus_mem_size += ptr_old->mem_size;
		memset(ptr_old, 0, BLK_SIZE);
		sum = sum - 1;
		
		
		return 1;
		
	}
	return 0;
}
#include "cw32_hal_uart.h"

/**
 * @brief 获取所属id的内存首地址,或者与type数值一样的首个数据地址
 *
 * @param id : 申请内存后获得的返回值
 * @param type :使用类型,用于异步操作时使用
 *        参数可以是: 0 - 不参与判断
 *           1 ~ 255
 * @return void * :所属id的内存首地址
 */
void *cw32_hal_get_mem_addr(uint8_t id,uint8_t type)
{
	if((id == 0) && (type == 0)) 
		return NULL;

	for(uint8_t i = 0; i < sum; i++)
	{
		mem_block *ptr_blk = (mem_block *) (MEM_START + BLK_SIZE * i);

		if(((id == 0) && (type == ptr_blk->mem_type))\
			 || (id == ptr_blk->mem_index))
		{
			return (ptr_blk->mem_ptr);
		}
	}
	return NULL;
}

/**
 * @brief 	获取所属id的内存首地址,或者与type数值一样的首个数据地址
 *
 * @param 	a : 用户存储的内存申请次数
 * @return 	uint8_t 1 - 内存池更新过 . 0 - 内存池使用数不变
 * @note 	由于内存池会因free销毁函数而进行位置的重组,所以必要时需要读取内存池的总数,与外部
			保存的总数进行比对,来判断是否需要重新通过cw32_hal_get_mem_addr函数来获取头数据
 */
uint8_t cw32_hal_mem_is_update(uint8_t* a)
{
	if(*a != sum)
	{
		*a = sum;
		return 1;
	}

	return 0;
}

/**
 * @brief 获取内存池剩余大小
 * @return uint16_t 内存池剩余大小
 */
uint16_t cw32_hal_get_mem_size(void)
{
	return surplus_mem_size;
}


